home *** CD-ROM | disk | FTP | other *** search
/ Professional Soft Collection 1.02 / Professional Soft Collection 1.02.iso / qemm.80c / technote.qip / QPI.TEC < prev    next >
Text File  |  1995-11-04  |  21KB  |  571 lines

  1.  
  2.          The QEMM Programming Interface - QPI
  3.  
  4.  Quarterdeck Technical Note #292             Filename: QPI.TEC
  5.  by Quarterdeck Development                CompuServe: QPI.TEC
  6.  Last Revised: 04/05/95                      Category: QEMM
  7.  
  8.  Subject: A discussion on programming issues when interfacing
  9.           with QEMM.
  10.  
  11.  
  12.  QPI:The QEMM Programming Interface
  13.  
  14.  The QEMM Programming Interface (QPI) lets programs request
  15.  information or services from QEMM. Programs can use the QPI to do
  16.  the following:
  17.  
  18.  Determine QEMM's status, and change that status if the system
  19.  configuration allows;
  20.  
  21.  Determine QEMM's version number;
  22.  
  23.  Determine whether QEMM's Stealth ROM feature is active, and if so
  24.  what Stealth ROM mode is in use;
  25.  
  26.  Determine the number of ROMs that QEMM is Stealthing and the
  27.  beginning segment address and length of each ROM;
  28.  
  29.  Determine whether QEMM is supporting the system's Suspend/Resume
  30.  features, and if so what interrupt these features are using;
  31.  
  32.  Determine whether QEMM is allowing or suppressing the BIOS calls
  33.  that make it possible to do work while waiting for disk activity
  34.  to complete, and tell QEMM to allow or suppress these calls if the
  35.  system configuration allows;
  36.  
  37.  Copy all or part of the contents of a Stealthed ROM into a buffer;
  38.  
  39.  Determine the physical memory mapped to any linear memory address,
  40.  and change the page table so that any page of physical memory is
  41.  mapped to any linear memory address;
  42.  
  43.  Read or write I/O ports, even if QEMM is trapping access to those
  44.  ports;
  45.  
  46.  Determine whether QEMM is trapping access to I/O ports, and tell
  47.  QEMM to trap access to ports on the calling program's behalf;
  48.  
  49.  Install a software routine that performs whatever actions the
  50.  program requires when a given I/O port is accessed;
  51.  
  52.  Simulate a hardware interrupt in such a way that it goes to the
  53.  correct DESQview or DESQview/X window.
  54.  
  55.  You can find sample QPI code and programs on the Quarterdeck
  56.  bulletin board and other electronic support locations.
  57.  
  58.  Getting the QPI Entry Point
  59.  
  60.  The first step in using the QPI is getting the double-word address
  61.  of the QPI entry point.
  62.  
  63.  The method of obtaining the entry point address that is described
  64.  here is available only in versions of QEMM higher than 6.00.
  65.  Programs that want to run with QEMM 5 must use a less
  66.  straightforward INT 2F interface to get the QPI entry point; for
  67.  more information, contact Quarterdeck via Compuserve (GO
  68.  QUARTERDECK), the Internet (support@qdeck.com) or our BBS and ask
  69.  for the QDMEM interface document.
  70.  
  71.  QEMM defines a DOS device driver called QEMM386$. To obtain the
  72.  entry point for QPI, do an IOCTL Read Control String call (INT 21,
  73.  function 4402h) to read four bytes from this device driver. Here
  74.  is a code sequence that demonstrates the details:
  75.  
  76.  
  77.  QEMMDeviceName db 'QEMM386$',0
  78.  QPIEntryPoint  dd ?
  79.  
  80.  GetQPIEntryPoint proc
  81.    mov  dx,offset QEMMDeviceName
  82.    mov  ax,3d00h
  83.    int  21h                      ; Try to open QEMM386$
  84.    jc  NoQEMM                    ; If CY, QEMM not present
  85.    mov  bx,ax                    ; Save file handle in BX
  86.    mov  dx,offset QPIEntryPoint  ; Store the entry point here
  87.    mov  cx,4                     ; Set up to read 4 bytes
  88.    mov  ax,4402h                 ; IOCTL Read Control String
  89.    int  21h
  90.    pushf                         ; Save the error code
  91.    mov  ah,3eh                   ; Close the handle
  92.    int  21h
  93.    popf                          ; Restore the error code
  94.    jc  NoQEMM                    ; If CY, QEMM is pre-6.00
  95.    ret
  96.  NoQEMM: stc
  97.    ret
  98.  GetQPIEntryPoint endp
  99.  
  100.  
  101.  QPI Functions
  102.  
  103.  Once you have stored the address of the QPI entry point, you make
  104.  all calls to QPI by loading AH or AX with the function number of
  105.  the call, setting the other registers to values appropriate to the
  106.  function, and making a far call to the entry point. The carry flag
  107.  is set on return if there is an error, or if the function number
  108.  is not valid in that version of QEMM.
  109.  
  110.  The QPI calls of interest to third-party programmers are listed
  111.  below. The version in which each of the calls was implemented is
  112.  noted.
  113.  
  114.  The QPI_GetStatus Call
  115.  
  116.  The QPI_GetStatus call tells you whether QEMM is on or off, and
  117.  whether it is in auto mode (see the AUTO/ON/OFF parameter in
  118.  Chapter 7 in the QEMM Reference Manual for more information). All
  119.  versions of QEMM support this call.
  120.  
  121.  
  122.  QPI_GetStatus    EQU   0
  123.     ; Takes    AH = 0
  124.     ; Returns   AL = 0 if on
  125.     ;       AL = 1 if auto/on
  126.     ;       AL = 2 if off
  127.     ;       AL = 3 if auto/off
  128.  
  129.  
  130.  The QPI_SetStatus Call
  131.  
  132.  The QPI_SetStatus call lets you set the status of QEMM. If QEMM is
  133.  forced on by a parameter (like the RAM parameter) or other
  134.  services that it provides, this call will have no effect. You
  135.  should therefore make the QPI_GetStatus call after the
  136.  QPI_SetStatus call to see if the first call was successful. All
  137.  versions of QEMM support this call.
  138.  
  139.  QPI_SetStatus    EQU   1
  140.      ; Takes   AH = 1
  141.      ;      AL = 0 if on
  142.      ;      AL = 1 if auto/on
  143.      ;      AL = 2 if off
  144.      ;      AL = 3 if auto/off
  145.  
  146.  
  147. The QPI_GetVersion Call
  148.  
  149.  The QPI_GetVersion call returns the QEMM version number in Binary
  150.  Coded Decimal form in AX and BX. For instance, the call will
  151.  return BX = 0750 (not BX = 0732) for QEMM version 7.5.  All
  152.  versions of QEMM support this call.
  153.  
  154.  QPI_GetVersion    EQU   3
  155.      ; Takes   AH = 3
  156.      ; Returns  BH = major version (in Binary Coded Decimal)
  157.      ;      BL = minor version (in Binary Coded Decimal)
  158.      ;      AX = same as BX
  159.  
  160.  
  161.  
  162. The QPI_GetInfo Call
  163.  
  164.  In QEMM version 6.00 and later, the QPI_GetInfo call returns an
  165.  ASCII letter in CL that tells QEMM's Stealth ROM mode (if any),
  166.  and a number in CH that tells which interrupt (not IRQ) QEMM is
  167.  monitoring (if any) to support Suspend/Resume features. In QEMM
  168.  version 7.00 and later, the call also returns the size of QEMM's
  169.  disk buffer in DL and a bit map of information about the disk
  170.  buffer in BH. Bit 1 of BH will be on if the disk buffer has
  171.  already been used; bit 0 will be on if QEMM is buffering only INT
  172.  13s into the page frame (DISKBUFFRAME) and off if all INT 13s into
  173.  nonlinear memory are being buffered (DISKBUF). Note that other
  174.  registers are not preserved by this call.
  175.  
  176.  
  177.  QPI_GetInfo     EQU   1E00h
  178.      ; Takes    AX = 1E00
  179.      ; Returns  BH = xxxxxxAB
  180.      ;    where A = 1 if disk buffer has been used yet, 0 if not
  181.      ;          B = 1 if DISKBUFFRAME buffer, 0 if DISKBUF buffer
  182.                        - not valid if DL = 0
  183.      ;          BL = reserved
  184.      ;          CL = Stealth ROM type (0 for no Stealth ROM, "M"
  185.      ;               or "F" otherwise, other Stealth ROM types possible
  186.      ;               in future)
  187.      ;          CH = Suspend/Resume INT number (0 = none)
  188.      ;          DL = size of QEMM disk buffer in K (if 0, disk buffer
  189.      ;               doesn't exist)
  190.      ;          DH, DI, SI = reserved
  191.  
  192.  The QPI_GetStealthCount Call
  193.  
  194.  The QPI_GetStealthCount tells how many ROMs QEMM is Stealthing.
  195.  QEMM versions 6.00 and later support this call.
  196.  
  197.  
  198.  QPI_GetStealthCount equ 1E01h
  199.      ;   Takes  AX = 1E01
  200.      ; Returns  BX = number of ROMs that are Stealthed
  201.  
  202.  
  203.  The QPI_GetStealthList Call
  204.  
  205.  The QPI_GetStealthList call gives the same information as the
  206.  QPI_GetStealthCount call, and also fills a buffer with information
  207.  on the location and size of each Stealthed ROM. QEMM versions 6.00
  208.  and later support this call.
  209.  
  210.  
  211.  QPI_GetStealthList equ 1E02h
  212.      ;   Takes   AX = 1E02
  213.      ;        ES:DI = buffer to hold the list of Stealthed ROMs
  214.      ; Returns   BX = number of ROMs that are Stealthed
  215.      ;     Table at ES:DI will be filled in with:
  216.      ;       dw ROM start segment
  217.      ;       dw Length of ROM in paragraphs
  218.      ;     for each ROM that is Stealthed
  219.  
  220.  
  221.  The QPI_GetPTE Call
  222.  
  223.  The QPI_GetPTE call returns the page table entry for any logical
  224.  page in the first 1088K of memory. In other words, if you pass
  225.  this call the address of any page in the first 1088K of memory,
  226.  the call will return (in an extended register) the doubleword page
  227.  table entry for that address, which includes, among other things,
  228.  information about which physical page of memory QEMM has mapped to
  229.  the logical address that you provided. QEMM versions 6.00 and
  230.  later support this call.
  231.  
  232.  CX should contain the number of the logical page in memory that
  233.  you want to affect; the highest valid CX is 010F. (Page numbers
  234.  refer to consecutive 4K sections of memory, aligned on 4K
  235.  boundaries: that is, 0000 refers to paragraph 0000-00FF, 0001 to
  236.  0100-01FF, etc.) EDX (the extended DX register) should contain a
  237.  page table entry, in the following format:
  238.  
  239.  Bit 0 is the Present bit. Any access to a page with this bit off
  240.  causes a page fault.
  241.  
  242.  Bit 1 is the Read/Write bit. Any writing to a page with this bit
  243.  off causes a page fault.
  244.  
  245.  Bit 2 is the User/Supervisor bit. Any access to this page when the
  246.  processor is at privilege level 3 causes a page fault.
  247.  
  248.  Bits 3 and 4 must be 0.
  249.  
  250.  Bit 5 is the Accessed bit. Any read or write of the page causes
  251.  the processor to turn on this bit.
  252.  
  253.  Bit 6 is the Dirty bit. Any write to the page causes the processor
  254.  to turn on this bit.
  255.  
  256.  Bits 7 and 8 must be 0.
  257.  
  258.  Bits 9, 10, and 11 are available for systems programmer use.
  259.  
  260.  Bits 12 through 31 are the page number.
  261.  
  262.  For instance, a page table entry 000FF007 means physical page
  263.  number 000FF (paragraph FF00-FFFF), which is not yet accessed nor
  264.  dirty, but which is present, writable and user-accessible.
  265.  
  266.  
  267.  QPI_GetPTE      equ 1F00h
  268.      ;   Takes   AX = 1F00
  269.      ;           CX = page number
  270.      ; Returns  EDX = page table entry for that page number
  271.  
  272.  
  273.  The QPI_SetPTE Call
  274.  
  275.  The QPI_SetPTE call lets you set the page table entry for any
  276.  logical page in the first 1088K of memory. In particular, this
  277.  means that you can tell QEMM to map any 4K of memory to any
  278.  4K-aligned address below the 1088K mark. QEMM versions 6.00 and
  279.  later support this call. See the section above on the QPI_GetPTE
  280.  call for more information.
  281.  
  282.  
  283.  QPI_SetPTE     equ   1F01h
  284.      ; Takes  AX = 1F01
  285.      ;        CX = page number
  286.      ;       EDX = page table entry to set at that page number
  287.  
  288.  
  289.  The QPI_GetVHIInfo Call
  290.  
  291.  The QPI_GetVHIInfo call, in conjunction with the QPI_SetVHIInfo
  292.  call, is primarily used by disk cache developers who wish to get
  293.  information on QEMM's safety precaution of suppressing the BIOS
  294.  INT 15 function 90 callout. This safety precaution, known as
  295.  VirtualHDIRQ or VHI (see the section on the VIRTUALHDIRQ:N
  296.  parameter in Chapter 7 in the QEMM Reference Manual for more
  297.  information), is normally in effect only when the disk interrupt
  298.  INT 13 is being Stealthed. If you have verified that the use of
  299.  INT 15 fn 90 in the disk cache you are developing is compatible
  300.  with QEMM's Stealth ROM feature, you will want to tell QEMM to
  301.  allow INT 15 function 90.
  302.  
  303.  The call returns flags in BL that give the VHI state. Bit 7 will
  304.  be on whenever QEMM is Stealthing INT 13 (if INT 13 is not
  305.  Stealthed, QEMM never suppresses INT 15 function 90); bit 0 will
  306.  be on if QEMM is currently suppressing INT 15 function 90. Bits
  307.  1-6 of the VHI bit map are reserved. QEMM versions 6.00 and later
  308.  support this call.
  309.  
  310.  
  311.  QPI_GetVHIInfo   equ   2000h
  312.      ;  Takes   AX = 2000
  313.      ; Returns  BL = AxxxxxxB
  314.      ;     where A = 1 if VHI is being paid attention to
  315.      ;           B = 1 if VHI is currently enabled
  316.      ;              (i.e. INT 15 fn 90 is currently suppressed)
  317.      ;           x = reserved
  318.  
  319.  The QPI_SetVHIInfo Call
  320.  
  321.  The QPI_SetVHIInfo call lets you turn on or off QEMM's safety
  322.  precaution of suppressing INT 15 function 90 whenever the disk
  323.  interrupt INT 13 is being Stealthed. (See the section above on the
  324.  QPI_GetVHIInfo call for more information.) To request a VHI state,
  325.  set BL to 1 to suppress INT 15 function 90, or set BL to 0 to
  326.  allow INT 15 fn 90. QEMM will return the previous VHI flags in BL.
  327.  If bit 7 of the returned flags is off, then QEMM is not paying
  328.  attention to the VHI state, and your request did not have an
  329.  effect. QEMM versions 6.00 and later support this call.
  330.  
  331.  
  332.  QPI_SetVHIInfo   equ   2001h
  333.      ;   Takes   AX = 2001
  334.      ;           BL = xxxxxxxB that you want (bit 7 is ignored)
  335.      ; Returns   BL = AxxxxxxB of previous VHI state;
  336.      ;           if A of output = 0, B of input was ignored
  337.  
  338.  
  339.  The QPI_CopyStealthRoms Call
  340.  
  341.  The QPI_CopyStealthRoms call tells QEMM to copy the contents of
  342.  part or all of a Stealthed ROM into a buffer in conventional
  343.  memory. This is the only reliable to access the contents of a
  344.  Stealthed ROM. QEMM versions 6.00 and later support this call.
  345.  
  346.  
  347.  QPI_CopyStealthRoms equ   2100h
  348.      ; Takes   AX = 2100
  349.      ;      DS:SI = Original address of ROM to copy
  350.      ;      ES:DI = Destination address in conventional memory
  351.      ;      ECX = # of bytes to copy
  352.      ; Returns  CY if no stealth or if DS:SI not within C000-FFFF
  353.  
  354.  
  355.  I/O Trapping
  356.  
  357.  The following calls make up the Quarterdeck QEMM I/O Trapping
  358.  Programming Interface. This interface allows a real-mode program
  359.  to specify I/O ports that QEMM should trap access to, as well as
  360.  I/O callback routines that QEMM will call whenever one of these
  361.  I/O ports is accessed. Using this interface, you can emulate
  362.  hardware devices that are accessible via I/O ports.
  363.  
  364.  When QEMM traps an I/O port, all accesses of that port, whether
  365.  input or output, are intercepted by QEMM. (QEMM traps certain I/O
  366.  ports itself, for proper management of virtual-8086 mode.)
  367.  Whenever an I/O port that a program has asked QEMM to trap is
  368.  accessed, QEMM calls a real-mode I/O callback routine. The same
  369.  callback routine is called for all trapped I/O ports.
  370.  
  371.  A program that wishes to trap an I/O port should:
  372.  
  373.  1) Use the QPI_GetVersion call to make sure that the version of
  374.     QEMM is 7.03 or later. Earlier versions do not support most of
  375.     the I/O Trapping Programming Interface. Alternatively, if the
  376.     version of QEMM does not support the call you have made, the
  377.     call will return with the carry flag set;
  378.  
  379.  2) Issue a QPI_GetPortTrap call to determine that another program
  380.     is not already trapping the port. If another program is
  381.     trapping the port, it is generally advisable not to install
  382.     your port trap;
  383.  
  384.  3) Get the address of the existing callback routine with the
  385.     QPI_GetIOCallback call. Because there is only one I/O callback
  386.     routine, and because multiple programs may request I/O
  387.     trapping, your callback routine must jump to the previous
  388.     callback routine whenever your routine is not interested in the
  389.     I/O port being accessed;
  390.  
  391.  4) Install its own far routine as the new callback routine, using
  392.     the QPI_SetIOCallback call. Your callback routine will be
  393.     passed the following information:
  394.  
  395.      AX = Data for output
  396.      CX = Type of I/O (see flag bits defined below)
  397.      DX = Port number
  398.      IF = 0 (interrupts are disabled)
  399.  
  400.  When the callback routine has finished its work, it should return
  401.  far with all registers other than CX and DX preserved. If the
  402.  routine is called to get input from a port, AX should be modified.
  403.  The bit-mapped word in CX contains the following information:
  404.  
  405.  
  406.  IOT_Output     equ   0000000000000100b
  407.      ;      bit 2 is 1 if output,
  408.      ;      0 if input
  409.  
  410.  
  411.  IOT_Word      equ   0000000000001000b
  412.      ;      bit 3 is 1 if word I/O,
  413.      ;      0 if byte I/O
  414.  
  415.  
  416.  IOT_IF       equ   0000001000000000b
  417.      ;      bit 9 is the same as the
  418.      ;      caller's interrupt flag
  419.  
  420.  
  421.  5) Specify which port to trap with the QPI_SetPortTrap call.
  422.  
  423.     If your program does not stay resident forever, it should do
  424.     the following before exiting:
  425.  
  426.  6) Use the QPI_GetIOCallback call to make sure that no one has
  427.     installed a callback routine after yours. If a handler is
  428.     installed after yours, you should remain resident;
  429.  
  430.  7) Remove its trap with the QPI_ClearPortTrap call. This call will
  431.     clear all traps on a particular I/O port, unless QEMM is
  432.     trapping that port for itself, in which case QEMM's trapping
  433.     alone will remain in effect for that port;
  434.  
  435.  8) Remove its callback by using the QPI_SetIOCallback call to set
  436.     the previously existing callback routine.
  437.  
  438.  The following restrictions apply to this interface:
  439.  
  440.  Only INs and OUTs of words or bytes are supported, not INs and
  441.  OUTs of doublewords. Also, string I/O (the INS and OUTS
  442.  instructions) are supported only as of QEMM version 7.5.
  443.  
  444.  QEMM cannot trap the I/O of VCPI protected-mode programs.
  445.  Furthermore, because Quarterdeck's DPMI driver (QDPMI) is
  446.  implemented as a VCPI client, QEMM cannot trap the I/O of DPMI
  447.  clients either. Furthermore, these traps are no longer in effect
  448.  when Microsoft Windows 386 enhanced mode is running.
  449.  
  450.  The following four calls allow you to bypass port trapping and
  451.  read and write I/O ports directly. QEMM 5.00 and later versions
  452.  support these four calls.
  453.  
  454.  
  455.  QPI_UntrappedIORead equ   1A00h
  456.      ; Takes   AX = 1A00
  457.      ;         DX = port to read
  458.      ; Returns BL = value read
  459.  
  460.  
  461.  QPI_UntrappedIOWrite equ   1A01h
  462.      ; Takes   AX = 1A01
  463.      ;         DX = port to write
  464.      ;         BL = value to write
  465.  
  466.  
  467.  QPI_UntrappedIOReadIndexed  equ   1A02h
  468.      ; Takes   AX = 1A02
  469.      ;         DX = base port to read
  470.      ;         BH = index into base port
  471.      ; Returns BL = value read
  472.  
  473.  
  474.  QPI_UntrappedIOWriteIndexed  equ   1A03h
  475.      ; Takes   AX = 1A03
  476.      ;         DX = base port to write
  477.      ;         BH = index into base port
  478.      ;         BL = value to write
  479.  
  480.  
  481.  The QPI_UntrappedIO Call
  482.  
  483.  The QPI_UntrappedIO call performs the same functions as the
  484.  QPI_UntrappedIORead and the QPI_UntrappedIOWrite calls, but it
  485.  uses register values that are similar to the ones QEMM passes to
  486.  your I/O callback routine (including the flags in CX that give
  487.  information about the type and size of the I/O and the caller's
  488.  interrupt flag). This call may therefore be easier to use from
  489.  within an I/O callback routine. QEMM 7.03 and later support this
  490.  call.
  491.  
  492.  
  493.  QPI_UntrappedIO   equ   1A04h
  494.      ; Takes   AX = 1A04
  495.      ;         BX = value to write
  496.      ;         DX = port to read or write
  497.      ;         CX = type of I/O (see description above
  498.      ;              of CX passed to callback routine)
  499.      ; Returns BX = value read
  500.  
  501.  The following five calls are described in the introduction above.
  502.  QEMM 7.03 and later versions support these calls.
  503.  
  504.  
  505.  QPI_GetIOCallback  equ   1A06h
  506.      ;    Takes    AX = 1A06
  507.      ; Returns  ES:DI = previous I/O callback function
  508.  
  509.  
  510.  QPI_SetIOCallback  equ   1A07h
  511.      ; Takes   AX = 1A07
  512.      ;      ES:DI = new I/O callback function
  513.  
  514.  
  515.  QPI_GetPortTrap   equ   1A08h
  516.      ; Takes   AX = 1A08
  517.      ;         DX = I/O port number
  518.      ; Returns BL = 0 if port not trapped,
  519.                BL = 1 if port already trapped
  520.  
  521.  
  522.  QPI_SetPortTrap   equ   1A09h
  523.      ; Takes   AX = 1A09
  524.      ;         DX = I/O port number
  525.  
  526.  
  527.  QPI_ClearPortTrap  equ   1A0Ah
  528.      ; Takes   AX = 1A0A
  529.      ;         DX = I/O port number
  530.  
  531.  
  532.  The QPI_SimulateHWInt Call
  533.  
  534.  The QPI_SimulateHWInt call can be used by callback routines that
  535.  wish to simulate a hardware interrupt. When DESQview or DESQview/X
  536.  is running, the interrupt handler that should receive the
  537.  interrupt may be in a different process from the current one. Use
  538.  QPI_SimulateHWInt to simulate an interrupt properly when DESQview
  539.  or DESQview/X is running. The DESQview API Reference Manual
  540.  describes how to determine when DESQview is running. QEMM 7.03 and
  541.  later versions support this call.
  542.  
  543.  QPI_SimulateHWInt  equ   1C04h
  544.      ; Takes   AX = 1C04
  545.      ;         BX = interrupt number to generate
  546.  
  547.  
  548.  The QPI Get Sub-Version String Call
  549.  
  550.  QPI_Get_QEMM_SubVer equ 1E05h
  551.  
  552.      ; Takes      AX = 1E05
  553.      ;            CX = Length of buffer
  554.      ;         ES:DI = buffer
  555.      ; Returns    CX = number of bytes which could not fit in buffer
  556.      ;            CY if function not supported
  557.      ; Fills in the given buffer with a null terminated string.  If
  558.      ; the actual length of the string is greater than the length of
  559.      ; the buffer (as passed in CX) then it clips the string to the
  560.      ; buffer length - 1 and puts a null in the last byte of the buffer
  561.      ; and returns the number of extra bytes in CX.  If everything
  562.      ; fits in the buffer, then the returned CX=0.
  563.  
  564.  ******************************************************************
  565.  *      Trademarks are property of their respective owners.       *
  566.  *   This and other technical notes may be available in updated   *
  567.  *     forms through Quarterdeck's standard support channels.     *
  568.  *          Copyright (C) 1995 Quarterdeck Corporation            *
  569.  ******************** E N D   O F   F I L E ***********************
  570.  
  571.